﻿/****************************** Module Header ******************************\
 * Module Name:  FormBinder.cs
 * Module Version:  1.0.0 (2012-8-25)
 * Copyright (c) AnyEB.Com (14507247@qq.com)
 * 
 * This class is used to extension winformcontrol instance's method.  It supplies 
 * public static extension methods to load data or get othor control.
 * 
 * This source is subject to the GPL License.
 * See http://www.gnu.org/licenses/gpl.html.
 * All other rights reserved.
 * 
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data;
using System.Linq;
using System.Text;
using System.Reflection;

namespace UCF.Core.Forms
{
    /// <summary>
    /// 表单绑定器
    /// <para>注意：ComboBox和WebBrowser控件需要特殊说明！</para>
    /// </summary>
    public class FormBinder
    {
        private Dictionary<string, string> MessageSet = new Dictionary<string, string>();

        /// <summary>
        /// 添加消息
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="title"></param>
        public void AddMessage(string msg, string title = "")
        {
            if (title.Length == 0) title = (this.MessageSet.Count + 1).ToString();
            this.MessageSet[title] = msg;
        }

        /// <summary>
        /// 检测表单参数类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="errTip"></param>
        /// <param name="minLength"></param>
        /// <param name="maxLength"></param>
        /// <returns></returns>
        public bool CheckParameter<T>(string value, string errTip, int minLength = 1, int maxLength = 0)
        {
            return value.IsValidParameter<T>(ref this.MessageSet, errTip, minLength, maxLength);
        }

        /// <summary>
        /// 检测是否有消息
        /// </summary>
        /// <returns></returns>
        public bool IsValidForm()
        {
            if (this.MessageSet.Count == 0) return true;
            MessageBox.Show(this.MessageSet.Values.ToString(Environment.NewLine));
            this.MessageSet.Clear();
            return false;
        }

        /// <summary>
        /// 绑定数据实体到表单控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="list"></param>
        /// <param name="controlPrefix"></param>
        public void BindForm<T>(ref T e, IList<Control> list, string controlPrefix = "tb")
        {
            if (e == null) return;
            Control c;
            Type t = typeof(T);
            object v;
            string name;

            // comboboxlist
            foreach (Control cbbi in list)
            {
                if (cbbi.GetType() != typeof(ComboBox)) continue;
                ComboBox cbb = cbbi as ComboBox;
                if (cbb == null || cbb.Items.Count == 0) continue;
                name = cbb.Name.Substring(controlPrefix.Length);
                PropertyInfo pi = t.GetProperty("{0}ID".Fmt(name));
                if (pi != null)
                {
                    if (pi.GetValue(e, null) != null) cbb.SelectedValue = pi.GetValue(e, null);
                    continue;
                }
                pi = t.GetProperty("{0}Name".Fmt(name));
                if (pi != null)
                {
                    if (pi.GetValue(e, null) != null) cbb.SelectedValue = pi.GetValue(e, null).ToString();
                    continue;
                }
                pi = t.GetProperty(name);
                if (pi != null && pi.GetValue(e,null)!=null)
                {
                    if (cbb.DataSource!=null && cbb.DataSource.GetType() == typeof(DataTable))
                    {
                        cbb.SelectedValue = pi.GetValue(e, null).ToString();
                    }
                    else
                    {
                        cbb.SelectedItem = pi.GetValue(e, null);
                    }
                    continue;
                }

            }

            // radiogroup
            foreach (Control g in list)
            {
                if (g.GetType() != typeof(Panel)) continue;
                Panel group = g as Panel;
                if (group == null || !group.HasChildren) continue;
                PropertyInfo pi = t.GetProperty("{0}".Fmt(group.Name.Substring(controlPrefix.Length)));
                if (pi == null) continue;
                foreach (Control rb in group.Controls)
                {
                    if (rb.GetType() == typeof(RadioButton))
                    {
                        if (rb.Name == "{0}{1}".Fmt(pi.Name, pi.GetValue(e, null)))
                        {
                            ((RadioButton)rb).Checked = true;
                            break;
                        }
                    }
                }
            }

            // normal
            foreach (PropertyInfo pi in t.GetProperties())
            {
                c = list.SingleOrDefault(a => a.Name == controlPrefix + pi.Name);
                if (c == null) continue;
                v = pi.GetValue(e, null);
                if (v == null) continue;
                // TextBox
                if (c.GetType() == typeof(TextBox))
                {
                    ((TextBox)c).Text = (pi.PropertyType == typeof(decimal?)) ? ((decimal)v).ToString("0.00") : v.ToString();
                    continue;
                }
                // Label
                if (c.GetType() == typeof(Label))
                {
                    ((Label)c).Text = v.ToString();
                    continue;
                }
                // CheckBox
                if (c.GetType() == typeof(CheckBox))
                {
                    ((CheckBox)c).Checked = v.ToString().ToBoolean();
                    continue;
                }
                // DateTimePicker
                if (c.GetType() == typeof(DateTimePicker))
                {
                    ((DateTimePicker)c).Value = v.ToString().ToDateTime();
                    continue;
                }
                if (c.GetType() == typeof(CustomControls.Editor.SoEditor))
                {
                    ((CustomControls.Editor.SoEditor)c).SetValue(v.ToString());
                    continue;
                }
                if (c.GetType() == typeof(PictureBox))
                {
                    ((PictureBox)c).ImageLocation = v.ToString();
                    continue;
                }
            }
        }

        /// <summary>
        /// 绑定数据实体到表单控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="list"></param>
        /// <param name="controlPrefix"></param>
        /*
        public void BindForm(ref DataTable dt, IList<Control> list, string controlPrefix = "tb")
        {
            if (dt.Rows.Count==0) return;
            Control c;
            object v;
            string name;

            // comboboxlist
            foreach (Control cbbi in list)
            {
                if (cbbi.GetType() != typeof(ComboBox)) continue;
                ComboBox cbb = cbbi as ComboBox;
                if (cbb == null || cbb.Items.Count == 0) continue;
                name = cbb.Name.Substring(controlPrefix.Length);
                
                if (dt.Columns.Contains("{0}ID".Fmt(name)))
                {
                    cbb.SelectedValue = dt.GetValue("{0}ID".Fmt(name));
                    continue;
                }
                if (dt.Columns.Contains("{0}Name".Fmt(name)))
                {
                    cbb.SelectedValue = pi.GetValue(e, null).ToString();
                    continue;
                }
                pi = t.GetProperty(name);
                if (pi != null && pi.GetValue(e, null) != null)
                {
                    if (cbb.DataSource != null && cbb.DataSource.GetType() == typeof(DataTable))
                    {
                        cbb.SelectedValue = pi.GetValue(e, null).ToString();
                    }
                    else
                    {
                        cbb.SelectedItem = pi.GetValue(e, null);
                    }
                    continue;
                }

            }

            // radiogroup
            foreach (Control g in list)
            {
                if (g.GetType() != typeof(Panel)) continue;
                Panel group = g as Panel;
                if (group == null || !group.HasChildren) continue;
                PropertyInfo pi = t.GetProperty("{0}".Fmt(group.Name.Substring(controlPrefix.Length)));
                if (pi == null) continue;
                foreach (Control rb in group.Controls)
                {
                    if (rb.GetType() == typeof(RadioButton))
                    {
                        if (rb.Name == "{0}{1}".Fmt(pi.Name, pi.GetValue(e, null)))
                        {
                            ((RadioButton)rb).Checked = true;
                            break;
                        }
                    }
                }
            }

            // normal
            foreach (PropertyInfo pi in t.GetProperties())
            {
                c = list.SingleOrDefault(a => a.Name == controlPrefix + pi.Name);
                if (c == null) continue;
                v = pi.GetValue(e, null);
                if (v == null) continue;
                // TextBox
                if (c.GetType() == typeof(TextBox))
                {
                    ((TextBox)c).Text = (pi.PropertyType == typeof(decimal?)) ? ((decimal)v).ToString("0.00") : v.ToString();
                    continue;
                }
                // Label
                if (c.GetType() == typeof(Label))
                {
                    ((Label)c).Text = v.ToString();
                    continue;
                }
                // CheckBox
                if (c.GetType() == typeof(CheckBox))
                {
                    ((CheckBox)c).Checked = v.ToString().ToBoolean();
                    continue;
                }
                // DateTimePicker
                if (c.GetType() == typeof(DateTimePicker))
                {
                    ((DateTimePicker)c).Value = v.ToString().ToDateTime();
                    continue;
                }
                if (c.GetType() == typeof(CustomControls.Editor.SoEditor))
                {
                    ((CustomControls.Editor.SoEditor)c).SetValue(v.ToString());
                    continue;
                }
                if (c.GetType() == typeof(PictureBox))
                {
                    ((PictureBox)c).ImageLocation = v.ToString();
                    continue;
                }
            }
        }
         */

        /// <summary>
        /// 获取表单数据实体
        /// <para>注意：WebBrowser类型的控件只抓取ID=Editor的控件的值</para>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="list">控件列表</param>
        /// <param name="controlPrefix"></param>
        /// <returns></returns>
        public T GetEntity<T>(ref T e, IList<Control> list, string controlPrefix = "tb")
        {
            Control c;
            ComboBox cbb;
            Type t = typeof(T);
            string v;
            string name;

            // combobox
            foreach (Control cbbi in list)
            {
                if (cbbi.GetType() != typeof(ComboBox)) continue;
                cbb = cbbi as ComboBox;
                if (cbb == null || cbb.SelectedItem == null) continue;
                name = cbb.Name.Substring(controlPrefix.Length);
                if (cbb.SelectedItem.GetType() == typeof(DataRow) || cbb.SelectedItem.GetType() == typeof(DataRowView))
                {
                    DataRowView dr = (DataRowView)cbb.SelectedItem;
                    PropertyInfo piID = t.GetProperty("{0}ID".Fmt(name));
                    PropertyInfo piName = t.GetProperty("{0}Name".Fmt(name));
                    if (piID != null) SetEntityValue(piID, ref e, dr[0].ToString());
                    if (piName != null) SetEntityValue(piName, ref e, dr[1].ToString());
                    if (piID == null && piName == null)
                    {
                        PropertyInfo pi = t.GetProperty(name);
                        if (pi != null) SetEntityValue(pi, ref e, dr[0].ToString()); // dr[1]改为dr[0]，有影响再论.
                    }
                }
                else
                {
                    PropertyInfo pi = t.GetProperty(name);
                    if (pi != null) SetEntityValue(pi, ref e, cbb.SelectedItem.ToString());
                }
            }

            // radiogroup
            foreach (Control g in list)
            {
                if (g.GetType() != typeof(Panel)) continue;
                Panel group = g as Panel;
                if (group == null || !group.HasChildren) continue;
                PropertyInfo pi = t.GetProperty("{0}".Fmt(group.Name.Substring(controlPrefix.Length)));
                if (pi == null) continue;
                foreach (Control rb in group.Controls)
                {
                    if (rb.GetType() == typeof(RadioButton))
                    {
                        if (((RadioButton)rb).Checked)
                        {
                            SetEntityValue(pi, ref e, rb.Name.Substring(pi.Name.Length));
                            break;
                        }
                    }
                }
            }

            //normal
            foreach (PropertyInfo pi in t.GetProperties())
            {
                c = list.SingleOrDefault(a => a.Name == controlPrefix + pi.Name);
                if (c == null) continue;

                // TextBox
                if (c.GetType() == typeof(TextBox))
                {
                    v = ((TextBox)c).Text;
                    if (v.Length == 0) continue;
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                // Label
                if (c.GetType() == typeof(Label))
                {
                    v = ((Label)c).Text;
                    if (v.Length == 0) continue;
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                // DateTimePicker
                if (c.GetType() == typeof(DateTimePicker))
                {
                    v = ((DateTimePicker)c).Value.ToString();
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                // CheckBox
                if (c.GetType() == typeof(CheckBox))
                {
                    SetEntityValue(pi, ref e, ((CheckBox)c).Checked.ToString());
                }
                // FormEditor
                if (c.GetType() == typeof(CustomControls.Editor.SoEditor))
                {
                    v = ((CustomControls.Editor.SoEditor)c).GetValue();
                    SetEntityValue(pi, ref e, v);
                    continue;
                }
                if (c.GetType() == typeof(PictureBox))
                {
                    SetEntityValue(pi, ref e, ((PictureBox)c).ImageLocation);
                    continue;
                }
            }
            return e;
        }

        /// <summary>
        /// 设置实体对象的值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pi"></param>
        /// <param name="e"></param>
        /// <param name="value"></param>
        private void SetEntityValue<T>(PropertyInfo pi, ref T e, string value)
        {
            if (pi == null || string.IsNullOrEmpty(value)) return;
            if (pi.PropertyType == typeof(string))
            {
                pi.SetValue(e, value, null);
                return;
            }
            if (pi.PropertyType == typeof(Guid?) || pi.PropertyType == typeof(Guid))
            {
                pi.SetValue(e, value.ToGuid(), null);
                return;
            }
            if (pi.PropertyType == typeof(int?) || pi.PropertyType == typeof(int))
            {
                pi.SetValue(e, value.ToInt(), null);
                return;
            }
            if (pi.PropertyType == typeof(short?) || pi.PropertyType == typeof(short))
            {
                pi.SetValue(e, value.ToShort(), null);
                return;
            }
            if (pi.PropertyType == typeof(DateTime?) || pi.PropertyType == typeof(DateTime))
            {
                pi.SetValue(e, value.ToDateTime(), null);
                return;
            }
            if (pi.PropertyType == typeof(decimal?) || pi.PropertyType == typeof(decimal))
            {
                pi.SetValue(e, value.ToDecimal(), null);
                return;
            }
            if (pi.PropertyType == typeof(double?) || pi.PropertyType == typeof(double))
            {
                pi.SetValue(e, value.ToDouble(), null);
                return;
            }
            if (pi.PropertyType == typeof(Single) || pi.PropertyType == typeof(Single?))
            {
                pi.SetValue(e, value.ToFloat(), null);
                return;
            }
            if (pi.PropertyType == typeof(bool?) || pi.PropertyType == typeof(bool))
            {
                pi.SetValue(e, value.ToBoolean(), null);
                return;
            }
            pi.SetValue(e, value, null);
        }

        /// <summary>
        /// 获取实体对象值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="e"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        private object GetEntityValue<T>(ref T e, string name)
        {
            PropertyInfo pi = typeof(T).GetProperty(name);
            if (pi == null) return null;
            return pi.GetValue(e, null);
        }
    }
}
